
from typing import List
from databases import Database
from analyzer.dormitory_data_analyzer import DormitoryDataAnalyzer
from analyzer.monitoring_data_analyzer import MonitoringDataAnalyzer
from analyzer.recharge_data_analyzer import RechargeDataAnalyzer
from dao import create_db, recharge_dao
from model import DATABASE_URL
from model.recharge import Recharge
from utils.time_utils import cur_year_and_semester, datetime_to_str
from x_com import xport_core
from x_com import source_api
import x_com_lib

# import sqlalchemy
from sqlalchemy.ext.asyncio import create_async_engine

from x_com.import_api import electricity_data_source_service_0_0_1

logger = xport_core.getLogger()

class ElectricityDataAnalysisService:
  # 
  database = Database(DATABASE_URL)
  # 
  engine =  create_async_engine(DATABASE_URL, echo=False)
  # 
  dormitory_data_analyzer: DormitoryDataAnalyzer
  monitoring_data_analyzer: MonitoringDataAnalyzer
  recharge_data_analyzer: RechargeDataAnalyzer

  def __init__(self):
    self.dormitory_data_analyzer = DormitoryDataAnalyzer()
    self.monitoring_data_analyzer = MonitoringDataAnalyzer()
    self.recharge_data_analyzer = RechargeDataAnalyzer()

  async def init_db(self):
    await self.database.connect()
    # 创建数据库
    await create_db()

  async def on_init(self):
    await self.init_db()
    async with self.engine.connect() as conn:
      try:
        await self.dormitory_data_analyzer.load_data_in_memory(conn)
      except Exception as e:
        print(f"e1 = {e}")

      try:
        await self.monitoring_data_analyzer.load_data_in_memory(conn)
      except Exception as e:
        print(f"e2 = {e}")
      


  async def on_finalize(self):
    logger.info("on_finalize...")

  # SubscribeData
  async def subscribe_data(self, ctx: xport_core.Context):
    subscibe_info = x_com_lib.PySubscribeTopicInfo()
    subscibe_info.tag = [] 
    subscibe_info.topic = "Monitoring"
    logger.info(f"节点 订阅 Monitoring 事件...")
    x_com_lib.stream.dxc_subscribe_topic(subscibe_info)
    subscibe_info.topic = "Recharge"
    logger.info(f"节点 订阅 Recharge 事件...")
    x_com_lib.stream.dxc_subscribe_topic(subscibe_info)
    subscibe_info.topic = "Dormitory"
    logger.info(f"节点 订阅 Dormitory 事件...")
    x_com_lib.stream.dxc_subscribe_topic(subscibe_info)
    # 
    await electricity_data_source_service_0_0_1.subscribe_data()

  # GetBuildingInfo
  async def get_building_info(self, ctx: xport_core.Context) -> source_api.BuildingInfo:
    # 
    building_info = source_api.BuildingInfo()
    building_info.occupied_num = self.dormitory_data_analyzer.occupied_num
    building_info.room_num = self.dormitory_data_analyzer.room_num()
    return building_info

  # GetBuildingRechargeInfo
  async def get_building_recharge_info(self, ctx: xport_core.Context) -> source_api.RechargeInfo:
    recharge_info = source_api.RechargeInfo()

    year, semester = cur_year_and_semester()
    async with self.engine.connect() as conn:
      recharge_list:  List[Recharge] = await recharge_dao.get_by_year_and_semester(conn, year, semester)

    # 构建楼栋的充值数据
    for ele in recharge_list:
      recharge_info.order_num += ele.recharge_num
      recharge_info.order_amount += ele.amount
      building_recharge_info = source_api.BuildingRechargeInfo()
      building_recharge_info.building = ele.building_name
      building_recharge_info.recharge_energy = ele.recharged
      building_recharge_info.recharge_amount = ele.amount
      recharge_info.building_recharge_datas.append(building_recharge_info)
    return recharge_info

  # GetRoomEnergyStatus
  async def get_room_energy_status(self, ctx: xport_core.Context,  param: source_api.RoomEnergyStatusRequest) -> source_api.RoomEnergyStatusPager:
    
    room_energy_status_pager = source_api.RoomEnergyStatusPager()
    total, room_energy_status_list =  self.monitoring_data_analyzer.get_room_info_by_page(param.page_index, param.page_size)
  
    room_energy_status_pager.total = total  
    room_energy_status_pager.page_size = param.page_size
    room_energy_status_pager.page_index = param.page_index
    for ele in room_energy_status_list:
      room_energy_status = source_api.RoomEnergyStatus()
      room_energy_status.room_name = f"{ele.building_name}-{ele.room_number}"
      room_energy_status.update_time = datetime_to_str(ele.update_time)
      room_energy_status.used = ele.used
      room_energy_status.remaining = ele.remaining
      room_energy_status.free = ele.free
      room_energy_status_pager.datas.append(room_energy_status)
    return room_energy_status_pager
  
  # GetUsedInfo
  async def get_use_info(self, ctx: xport_core.Context) -> source_api.UseInfo:
    use_info = source_api.UseInfo()

    # 获取学院维度的用电量
    organization_room_dict = self.dormitory_data_analyzer.get_organization_room()
    organization_use_dict = self.monitoring_data_analyzer.get_use_by_organization(organization_room_dict)

    for organization, use in organization_use_dict.items():
      organization_use = source_api.OrganizationUseInfo()
      organization_use.organization = organization
      organization_use.use = use
      use_info.organization_use_datas.append(organization_use)

    # 获取楼栋维度的用电量
    for building, use in self.monitoring_data_analyzer.building_use_dict.items():
      building_use = source_api.BuildingUseInfo()
      building_use.building_name = building
      building_use.use = use
      use_info.building_use_datas.append(building_use)
    # 获取时间段维度的用电量
    for hour_segment, use in self.monitoring_data_analyzer.hour_segment_use_dict.items():
      hour_segment_use = source_api.HourSegmentUseInfo()
      hour_segment_use.hour_segment = hour_segment
      hour_segment_use.use = use
      use_info.hour_segment_use_datas.append(hour_segment_use)

    return use_info

